/**
 * Copyright 2016 JustWayward Team
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.songcha.module_bookreader.ui.view.readview;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import androidx.core.content.ContextCompat;

import android.graphics.Typeface;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;

import com.songcha.library_common.util.ToastUtil;
import com.songcha.module_bookreader.R;
import com.songcha.module_bookreader.utils.AppUtils;
import com.songcha.module_bookreader.utils.FileUtils;
import com.songcha.module_bookreader.utils.LogUtils;
import com.songcha.library_common.ui.view.HeaderBarView;
import com.songcha.library_common.util.FontUtil;
import com.songcha.library_common.util.ScreenUtil;
import com.songcha.library_common.util.StatusBarUtil;
import com.songcha.library_common.util.StringUtil;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Vector;

/***
 * 处理抽象的读取和绘制
 */
public class ReadPageFactory {
    private Context mContext;
    /**
     * 屏幕宽高
     */
    private int mHeight, mWidth;
    /**
     * 文字区域宽高
     */
    private int mVisibleHeight, mVisibleWidth;
    /**
     * 间距
     */
    private int mMarginHeight, mMarginWidth,mMarginTop,mMarginBottom;
    /**
     * 字体大小
     */
    private int  mFontSize;
    /**
     * 每页行数
     */
    private int mPageLineCount;
    /**
     * 行间距
     **/
    private int mLineSpace;
    /**
     * 字节长度
     */
    private int mbBufferLen;
    /**
     * MappedByteBuffer：高效的文件内存映射
     */
    private MappedByteBuffer mbBuff;
    /**
     * 页首页尾的位置
     */
    private int curEndPos = 0, curBeginPos = 0, tempBeginPos, tempEndPos,mLastSaveBeginPos;
    private int currentChapter, tempChapter;
    private Vector<String> mLines = new Vector<>();

    private Paint mPaint;
    private Paint mTitlePaint;
    private Paint mBottomTextPaint;
    private Paint mChapterLastAdvertCountDownTextPaint;
    private Bitmap mBookPageBg;

    private SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm");
    private int timeLen = 0, percentLen = 0;
    private String time;
    private int battery = 40;
    private Rect rectF;
    private ProgressBar batteryView;
    private Bitmap batteryBitmap;
    private String bookId;
    private List<String> chaptersList;
    private int chapterSize = 0;
    private int currentPage = 1;

    private BaseReadView.IOnReadStateChangeListener listener;
    private String charset = "UTF-8";

    private boolean mIsOnDrawWord = true;
    private BaseReadView.IOnWordListener mOnWordListener;
    private String mFontPath = "";
    private boolean mIsFromSD = false;
    private final static int BATTERY_WIDTH=(int)ScreenUtil.dp2px(22);
    private final static int BATTERY_HEIGHT=(int)ScreenUtil.dp2px(11);
    private int mLineSpaceRatio=5;
    private int mFontHeight=0;

    public void setIsOnDrawWord(boolean drawWord){
        mIsOnDrawWord=drawWord;
    }

    public void setOnWordListener(BaseReadView.IOnWordListener onWordListener){
        mOnWordListener=onWordListener;
    }

    public void setFontPath(String fontPath){
        mFontPath=fontPath;
        if(mIsOnDrawWord && !mFontPath.equals("")){
            Typeface typeface = Typeface.createFromFile(mFontPath);
            mPaint.setTypeface(typeface);
        }
    }

    private void setCurrentPage(int page){
        currentPage = page;
    }

    public int getCurrentPage(){
        return currentPage;
    }

    public void setChapterList(List<String> chaptersList){
        this.chaptersList=chaptersList;
    }

    /*public ReadPageFactory(Context context, String bookId, boolean isOnDrawWord, BaseReadView.IOnWordListener onWordListener, String fontPath, boolean isFromSD) {
        this(context, ScreenUtil.getScreenWidth(), ScreenUtil.getScreenRealHeight(),
                SettingManager.getInstance().getReadFontSize(),
                bookId,isOnDrawWord, onWordListener,fontPath,isFromSD);
    }*/
    private Canvas mCurCanvas,mNextCanvas;

    public ReadPageFactory(Context context, int width, int height, int fontSize, String bookId,
                           boolean isOnDrawWord, BaseReadView.IOnWordListener onWordListener,
                           String fontPath, boolean isFromSD,Canvas curCanvas,Canvas nextCanvas) {
        mContext = context;
        mWidth = width;
        mHeight = height;
        mFontSize = fontSize;
        setFontHeight();
        setLineSpace();

        mCurCanvas = curCanvas;
        mNextCanvas = nextCanvas;

        mIsOnDrawWord=isOnDrawWord;
        mOnWordListener=onWordListener;
        mFontPath=fontPath;
        mIsFromSD=isFromSD;

        //mNumFontSize = ScreenUtils.dpToPxInt(16);
        //mNumFontSize = (int)ScreenUtil.sp2px(16);
        mMarginWidth = (int)ScreenUtil.dp2px(15);
        //marginHeight = (int)ScreenUtil.dp2px(20);
        if(context instanceof Activity){
            mMarginTop = StatusBarUtil.getStatusBarHeight((Activity)mContext) + HeaderBarView.Companion.getDEFAULT_HEIGHT(); //(int)ScreenUtil.dp2px(42);//StatusBarUtil.getStatusBarHeight(context); //(int)ScreenUtil.dp2px(15);
        }else{
            mMarginTop = (int)ScreenUtil.dp2px(42); //(int)ScreenUtil.dp2px(42);//StatusBarUtil.getStatusBarHeight(context); //(int)ScreenUtil.dp2px(15);
        }
        mMarginBottom= (int)ScreenUtil.dp2px(32);
       // mVisibleHeight = mHeight - marginHeight * 2 - mNumFontSize * 2 - mLineSpace * 2;
       // mVisibleHeight = mHeight - marginTop -marginBottom - mFontSize * 2 - mLineSpace * 2;
        setVisibleHeight();
        mVisibleWidth = mWidth - mMarginWidth * 2;
        setPageLineCount(0);
        rectF = new Rect(0, 0, mWidth, mHeight);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTextSize(mFontSize);
        if(mIsOnDrawWord && !mFontPath.equals("")){
            Typeface typeface = Typeface.createFromFile(mFontPath);
            mPaint.setTypeface(typeface);
        }

        //mPaint.setTextSize(ContextCompat.getColor(context, R.color.chapter_content_day));
        //mPaint.setColor(ContextCompat.getColor(context, R.color.chapter_content_day));
        mPaint.setColor(Color.BLACK);

        mTitlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTitlePaint.setTextSize(mFontSize);
        mTitlePaint.setColor(ContextCompat.getColor(AppUtils.getAppContext(), R.color.chapter_title_day));

        mBottomTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBottomTextPaint.setTextSize(ScreenUtil.sp2px(12f));
        mBottomTextPaint.setColor(Color.parseColor("#4D4949"));

        mChapterLastAdvertCountDownTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mChapterLastAdvertCountDownTextPaint.setTextSize(ScreenUtil.sp2px(14f));
        mChapterLastAdvertCountDownTextPaint.setColor(Color.parseColor("#4D4949"));

        mBottomFontMetrics = FontUtil.getFontMetrics(ScreenUtil.sp2px(12f),false,null);

        timeLen = (int) mBottomTextPaint.measureText("00:00");
        percentLen = (int) mBottomTextPaint.measureText("00.00%");
        // Typeface typeface = Typeface.createFromAsset(context.getAssets(),"fonts/FZBYSK.TTF");
        // mPaint.setTypeface(typeface);
        // mNumPaint.setTypeface(typeface);

        this.bookId = bookId;
        this.chaptersList = chaptersList;


        time = dateFormat.format(new Date());
    }

    public void setMarginTop(int marginTop){
        mMarginTop=marginTop;
        setVisibleHeight();
    }


    public int getCurBeginPos(){
        return curBeginPos;
    }

    public int getCurChapter(){
        return currentChapter;
    }

    public int getChapterSize(){
        return chapterSize;
    }

    public int getCurEndPos(){
        return curEndPos;
    }

    public void setCurEndPos(int endPos){
         curEndPos = endPos;
    }

    public int getBufferLen(){
        return mbBufferLen;
    }

    /**
     * 标题和电量在top和bottom绘制，剩下的就是visibleHeight
     */
    private void setVisibleHeight(){
        mVisibleHeight = mHeight - mMarginTop - mMarginBottom;
        //mVisibleHeight = mHeight - marginTop -marginBottom - mFontHeight - mLineSpace*2;
       // LogUtils.d("aaa setVisibleHeight",mVisibleHeight+","+mHeight+","+marginTop+","+marginBottom+","+mFontHeight+","+mLineSpace);
    }

    /***
     * 设置一页有多少行
     * @param paraSpace
     */
    private void setPageLineCount(int paraSpace){
        //should be fontheight+linespace
        mPageLineCount = (mVisibleHeight-mLineSpace-paraSpace) / (mFontHeight + mLineSpace);
    }

    private Paint.FontMetrics mFontMetrics;
    private Paint.FontMetrics mBottomFontMetrics;

    private void setFontHeight(){
        mFontMetrics=FontUtil.getFontMetrics(mFontSize,false,null);
        mFontHeight=(int)(mFontMetrics.bottom-mFontMetrics.top);
    }

    public File getBookFile(int chapter) {
        File file = FileUtils.getChapterFile(bookId, chapter);
        if (file != null && file.length() > 10) {
            // 解决空文件造成编码错误的问题
            charset = FileUtils.getCharset(file.getAbsolutePath());

        }
        LogUtils.i("charset=" + charset);
        return file;
    }

    /*public void openBook() {
        openBook(new int[]{0, 0});
    }*/

    public void openBook(int[] position) {
        openBook(1, position);
    }

    /**
     * 打开书籍文件
     *
     * @param chapter  阅读章节
     * @param position 阅读位置
     * @return 0：文件不存在或打开失败  1：打开成功
     */
    public int openBook(int chapter, int[] position) {
        if(chaptersList.size() == 0) return 0;
        this.currentChapter = chapter;
        this.chapterSize = chaptersList.size();
        if (currentChapter > chapterSize)
            currentChapter = chapterSize;
        String path = getBookFile(currentChapter).getPath();
        try {
            File file = new File(path);
            long length = file.length();
            if (length > 0) {
                mbBufferLen = (int) length;
                // 创建文件通道，映射为MappedByteBuffer
                mbBuff = new RandomAccessFile(file, "r")
                        .getChannel()
                        .map(FileChannel.MapMode.READ_ONLY, 0, length);
                curBeginPos = position[0];
                curEndPos = position[1];
                //if(isOnChapterChange)
                    onChapterChanged(chapter);
                mLines.clear();
                return 1;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    enum DrawType{
        TEXT,
        BATTERY,
        PROGRESS,
        TIME,
        ALL
    }

    //是否点击letter
    public String clickLetter(float x,float y){
        if(!mIsOnDrawWord) return null;
        for(int i=0;i<mWordLocationList.size();i++){
            //先搜索y坐标，再搜索x坐标
            List<WordLocation> temp=mWordLocationList.get(i);
            if(temp.size()==0) continue;
            WordLocation Ylocation=temp.get(0);
            if(y>=Ylocation.startY && y<=Ylocation.endY){
                for(int j=0;j<temp.size();j++){
                    WordLocation Xlocation = temp.get(j);
                    if(x>=Xlocation.startX && x<=Xlocation.endX){
                        if(!Xlocation.word.equals(""))
                            return Xlocation.word;
                        break;
                    }else{
                        continue;
                    }
                }
            }else{
                continue;
            }

        }
        return null;
    }

    class WordLocation{
        float startY=0;
        float endY=0;
        float startX=0;
        float endX=0;
        String word="";
    }

    private List<List<WordLocation>> mWordLocationList=new ArrayList<>();
    List<String> mPunctuations=Arrays.asList(new String[]{"\"",",","?","\'","!",".","…"});

    enum ReaderLoadState{
        LOADING,
        LOAD_SUCCESS,
        LOAD_ERROR,
    }

    /**
     * 绘制阅读页面
     * 虚假的ondraw，只是设置变量，只有在postinvalidate的时候才会真正绘制
     * @param canvas
     */

    private ReaderLoadState mCurCanvasState = ReaderLoadState.LOADING;
    private ReaderLoadState mNextCanvasState = ReaderLoadState.LOADING;

    public ReaderLoadState getCurCanvasLoadState(){
        return mCurCanvasState;
    }

    public ReaderLoadState getNextCanvasLoadState(){
        return mNextCanvasState;
    }

    private void drawLoadTextCanvas(Canvas canvas,String str){
        float fontWidth = FontUtil.measureText(str,mFontSize,false,null);
        canvas.drawText(str,(mWidth - fontWidth) / 2,(mHeight / 2) + (mFontHeight / 2 - mFontMetrics.bottom),mPaint);
    }

    private boolean drawLoadText(Canvas canvas,ReaderLoadState state){
        if(state == ReaderLoadState.LOADING){
            drawLoadTextCanvas(canvas,"加载中...");
            return true;
        }else if(state == ReaderLoadState.LOAD_ERROR){
            drawLoadTextCanvas(canvas,"加载失败");
            return true;
        }
        return false;
    }

    private boolean mCurCanvasIsDrawAdvert = false;
    private boolean mNextCanvasIsDrawAdvert = false;

    public boolean getCurCanvasIsDrawAdvert(){
        return mCurCanvasIsDrawAdvert;
    }

    private boolean saveCanvasLoadState(Canvas canvas,ReaderLoadState state){
        if(canvas == mNextCanvas){
            if(state != null)
                mNextCanvasState = state;
            if(mNextCanvasState != null){
                drawBg(canvas);
                if(drawLoadText(canvas,mNextCanvasState)) return true;
            }
        }else{
            if(state != null)
                mCurCanvasState = state;
            drawBg(canvas);
            if(drawLoadText(canvas,mCurCanvasState)) return true;
        }
        return false;
    }

    public void drawPageLastAdvertCountDown(int countDown){
        drawBg(mCurCanvas);
        String text = "滑动可继续阅读";
        if(countDown > 0)
            text = (countDown) + "秒后，" + text;
        float textLen = mChapterLastAdvertCountDownTextPaint.measureText(text);
        mCurCanvas.drawText(text,(mWidth - textLen) / 2,mHeight - ScreenUtil.dp2px(20),mChapterLastAdvertCountDownTextPaint);
    }

    private boolean saveCanvasIsDrawAdvert(Canvas canvas,boolean isDrawAdvert){
        if(canvas == mNextCanvas){
            mNextCanvasIsDrawAdvert = isDrawAdvert;
        }else{
            mCurCanvasIsDrawAdvert = isDrawAdvert;
        }
        if(isDrawAdvert){
            drawBg(canvas);
            return true;
        }
        return false;
    }

    public synchronized void drawCanvas(Canvas canvas,ReaderLoadState state,boolean isDrawAdvert) {
        if(saveCanvasLoadState(canvas,state))
            return;
        if(saveCanvasIsDrawAdvert(canvas,isDrawAdvert))
            return;

        if (mLines.isEmpty()) {
            if(mIsToPageLast){
                /*int ret = openBook(currentChapter, new int[]{0, 0});
                if(ret>0){
                    mLines = pageLast();
                    onPageChanged(currentChapter, currentPage);
                    mIsToPageLast=false;
                }*/
            }else{
                initCurrentPage(curEndPos);
                curEndPos = curBeginPos;
                mLines = pageDown();
            }
        }

        if (mLines.isEmpty()) return;
        //int y = marginHeight + (mLineSpace << 1);
        int y = mMarginTop + (mLineSpace << 1);
        drawBg(canvas);
        drawTitle(canvas);
        drawReadText(canvas,y);
        drawBattery(canvas);
        drawProgress(canvas);
        drawCurrentTime(canvas);
    }

    private void drawTitle(Canvas canvas){
        //canvas.drawText(chaptersList.get(currentChapter - 1), marginWidth, marginTop+mLineSpace, mTitlePaint);
        //canvas.drawText(chaptersList.get(currentChapter - 1), mMarginWidth, 50, mTitlePaint);
    }

    /***
     * 画背景，同时可以清空画布
     * @param canvas
     */
    private void drawBg(Canvas canvas){
        if (mBookPageBg != null) {
            canvas.drawBitmap(mBookPageBg, null, rectF, null);
        } else {
            canvas.drawColor(Color.WHITE);
        }
    }

    /*private void saveReadProgress(){
        if(mLastSaveBeginPos!=curBeginPos){
            SettingManager.getInstance().saveReadProgress(bookId, currentChapter, curBeginPos, curEndPos);
            mLastSaveBeginPos=curBeginPos;
        }
    }*/

    private void drawBattery(Canvas canvas){
        // 绘制电量
        if (batteryBitmap != null) {
            float left=mWidth-mMarginWidth-BATTERY_WIDTH;
            float top=mHeight-ScreenUtil.dp2px(15)-BATTERY_HEIGHT;
            canvas.drawBitmap(batteryBitmap,left,top,mTitlePaint);
        }
    }

    private void drawProgress(Canvas canvas){
        float percent = 0;
        //current text/current chapter total text
        percent = (float) curEndPos * 100 / mbBufferLen;
        String str = StringUtil.float2PlainString(percent);
        canvas.drawText(str + "%",mMarginWidth,mHeight - ScreenUtil.dp2px(15) - ScreenUtil.dp2px(1),mBottomTextPaint);
    }

    private void drawCurrentTime(Canvas canvas){
        //String mTime = dateFormat.format(new Date());
        //align bottom that need to sub battery bottom border
        canvas.drawText(time, mWidth - mMarginWidth - BATTERY_WIDTH - ScreenUtil.dp2px(5) - timeLen, mHeight-ScreenUtil.dp2px(15) - ScreenUtil.dp2px(1), mBottomTextPaint);

    }

    /***
     * 绘制阅读页面文字
     * @param canvas
     * @param y
     */
    private void drawReadText(Canvas canvas,int y){
        //y += mLineSpace + mFontHeight;
        y=mMarginTop+mFontHeight/2+(int) mFontMetrics.bottom;

        mWordLocationList.clear();

        int lineIndex=0;
        for (String line : mLines) {
            y += mLineSpace;

            //根据单词绘制
            if(mIsOnDrawWord){


                float x=mMarginWidth;

                float spaceWidth=mPaint.measureText(" ");
                String[] arr=line.split(" ");

                List<WordLocation> locations=new ArrayList<>();

                //LogUtils.d("aaa",line);

                for(int i=0;i<arr.length;i++){
                    String word=arr[i];
                    if(word.endsWith("@")){
                        word=word.substring(0, word.length() - 1);
                    }

                    //去除标点符号,中间为'符号不去除
                    //最多三个元素，头,word，尾
                    String[] wordPunList=trimPunctuations(word);
                    if(wordPunList!=null){
                        float wordStartX=0;
                        float wordEndX=0;

                        String pun1=wordPunList[0];
                        String trimWord=wordPunList[1];
                        String pun2=wordPunList[2];

                        String completionWord=autoCompletionWord(lineIndex,i,arr.length,trimWord);

                        if(!pun1.equals("")){
                            mPaint.setColor(Color.BLACK);
                            canvas.drawText(pun1,x,y,mPaint);
                            x+=mPaint.measureText(pun1);
                        }
                        if(!trimWord.equals("")){
                            if(mOnWordListener!=null && mOnWordListener.isMarkWord(completionWord)){
                                mPaint.setColor(Color.parseColor("#ff8800"));
                            }else{
                                mPaint.setColor(Color.BLACK);
                            }
                            canvas.drawText(trimWord,x,y,mPaint);
                            wordStartX=x;
                            float wordWidth=mPaint.measureText(trimWord);
                            wordEndX=wordStartX+wordWidth;
                            x+=wordWidth;
                        }
                        if(!pun2.equals("")){
                            mPaint.setColor(Color.BLACK);
                            canvas.drawText(pun1,x,y,mPaint);
                            x+=mPaint.measureText(pun2);
                        }

                        Paint.FontMetrics fm = FontUtil.Companion.getFontMetrics(mPaint.getTextSize(),false,null);

                        if(fm!=null){
                            WordLocation location=new WordLocation();
                            location.startX=wordStartX;
                            location.endX=wordEndX;
                            location.startY=y+fm.ascent;
                            location.endY=y+fm.descent;
                            location.word=completionWord;
                            locations.add(location);
                        }

                        if(i<arr.length-1){
                            canvas.drawText(" ",x,y,mPaint);
                            x+=spaceWidth;
                        }


                    }else{
                       //画多余的空格
                        canvas.drawText(" ",x,y,mPaint);
                        x+=spaceWidth;
                    }


                }

                mWordLocationList.add(locations);

            }else{
                if (line.endsWith("@")) {
                    canvas.drawText(line.substring(0, line.length() - 1), mMarginWidth, y, mPaint);
                    y += mLineSpace;
                } else {
                    canvas.drawText(line, mMarginWidth, y, mPaint);
                }
            }

            y += mFontHeight;

            lineIndex++;

        }
    }

    private String autoCompletionWord(int lineIndex,int wordIndex,int wordSize, String word){
        String completionWord=word;
        //换行单词自动补全
        if(wordIndex==0){
            if(lineIndex>0){
                String lastLine=mLines.get(lineIndex-1);
                String[] tempArr=lastLine.split(" ");
                if(tempArr.length>0){
                    String lastWord=tempArr[tempArr.length-1];
                    if(lastWord.endsWith("@")){
                        lastWord=lastWord.substring(0,lastWord.length()-1);
                    }
                    if(!mLines.get(lineIndex).startsWith(" ") && !lastLine.endsWith(" ")){
                        String[] arr=trimPunctuations(lastWord);
                        if(arr!=null){
                            String trimWord=arr[1];
                            completionWord=trimWord+completionWord;
                        }

                    }
                }

            }
        } else if(wordIndex==wordSize-1){
            if(lineIndex<mLines.size()-1){
                String nextLine=mLines.get(lineIndex+1);
                String[] tempArr=nextLine.split(" ");
                if(tempArr.length>0) {
                    String nextWord = tempArr[0];
                    if(!mLines.get(lineIndex).endsWith(" ") && !nextLine.startsWith(" ")){
                        String[] arr=trimPunctuations(nextWord);
                        if(arr!=null){
                            String trimWord=arr[1];
                            completionWord=completionWord+trimWord;
                        }
                    }
                }
            }
        }
        return completionWord;
    }

    //split punctuation mark
    private String[] trimPunctuations(String word){
        if(word.equals("")) return null;

        String[] wordPunList={"","",""};

        int punStartIndex=-1;
        int wordStartIndex=-1;
        int wordEndIndex=-1;

        for(int j=0;j<word.length();j++){
            String letter=String.valueOf(word.charAt(j));

            if(!mPunctuations.contains(letter) || (letter.equals("'") && j<word.length()-1)){
                if(wordStartIndex>-1){
                    wordEndIndex=j;
                }else{
                    wordStartIndex=j;
                }

            }else{
                if(wordStartIndex==-1)
                    punStartIndex=j;
            }

        }

        //  LogUtils.d("aaa__",word);

        String realWord="";


        if(punStartIndex>-1){
            String pun=word.substring(0,punStartIndex+1);
            wordPunList[0]=pun;
        }
        if(wordEndIndex>-1){
            realWord=word.substring(wordStartIndex,wordEndIndex+1);
            wordPunList[1]=realWord;

            if(wordEndIndex<word.length()-1){
                String pun=word.substring(wordEndIndex+1);
                wordPunList[2]=pun;
            }
        }else{
            if(wordStartIndex>-1){
                mPaint.setColor(Color.GREEN);
                realWord=word.substring(wordStartIndex,wordStartIndex+1);
                wordPunList[1]=realWord;
            }

        }

        return wordPunList;


        }

    /**
     * 指针移到上一页页首
     */
    private void pageUp() {
        String strParagraph = "";
        Vector<String> lines = new Vector<>(); // 页面行
        int paraSpace = 0;
        setPageLineCount(0);
        while ((lines.size() < mPageLineCount) && (curBeginPos > 0)) {
            Vector<String> paraLines = new Vector<>(); // 段落行
            byte[] parabuffer = readParagraphBack(curBeginPos); // 1.读取上一个段落

            curBeginPos -= parabuffer.length; // 2.变换起始位置指针
            try {
                strParagraph = new String(parabuffer, charset);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            strParagraph = strParagraph.replaceAll("\r\n", "  ");
            strParagraph = strParagraph.replaceAll("\n", " ");

            while (strParagraph.length() > 0) { // 3.逐行添加到lines
                int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
                paraLines.add(strParagraph.substring(0, paintSize));
                strParagraph = strParagraph.substring(paintSize);
            }
            lines.addAll(0, paraLines);

            while (lines.size() > mPageLineCount) { // 4.如果段落添加完，但是超出一页，则超出部分需删减
                try {
                    curBeginPos += lines.get(0).getBytes(charset).length; // 5.删减行数同时起始位置指针也要跟着偏移
                    lines.remove(0);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            curEndPos = curBeginPos; // 6.最后结束指针指向下一段的开始处
            if(lines.size() < mPageLineCount){
                paraSpace += mLineSpace;
                setPageLineCount(paraSpace);
            }
            //mPageLineCount = (mVisibleHeight - paraSpace) / (mFontSize + mLineSpace); // 添加段落间距，实时更新容纳行数
        }
    }

    //从头进行读取以正确设置当前页数
    public void initCurrentPage(int curEndPos){
        if(mIsFromSD) return;
        currentPage = 0;
        setCurEndPos(0);
        //第一页也要读取
        while((curEndPos == 0 && currentPage == 0) || this.curEndPos < curEndPos){
            pageDown();
            currentPage++;
        }
        if(curEndPos > 0 && this.curEndPos > curEndPos){
            this.curEndPos = curEndPos;
            currentPage--;
        }
    }


    /**
     * 根据起始位置指针，读取一页内容
     * currentPage在此方法后设置
     * @return
     */
    private Vector<String> pageDown() {
        String strParagraph = "";
        Vector<String> lines = new Vector<>();
        //paragraph spacing
        int paraSpace = 0;
        setPageLineCount(0);
        while ((lines.size() < mPageLineCount) && (curEndPos < mbBufferLen)) {
            byte[] parabuffer = readParagraphForward(curEndPos);
            curEndPos += parabuffer.length;
            try {
                strParagraph = new String(parabuffer, charset);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            strParagraph = strParagraph.replaceAll("\r\n", "  ")
                    .replaceAll("\n", " "); // 段落中的换行符去掉，绘制的时候再换行

            while (strParagraph.length() > 0) {
                float[] measureWidth={0};
                int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, measureWidth);
                String str = strParagraph.substring(0, paintSize);
                lines.add(str);
                strParagraph = strParagraph.substring(paintSize);
                if (lines.size() >= mPageLineCount) {
                    break;
                }
            }
            //add @ to paragraph last that convenient for add paragraph spacing
            lines.set(lines.size() - 1, lines.get(lines.size() - 1) + "@");
            //move pointer to content overflow position
            if (strParagraph.length() != 0) {
                try {
                    curEndPos -= (strParagraph).getBytes(charset).length;
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            //not sett line count for last line
            if(lines.size() < mPageLineCount){
                paraSpace += mLineSpace;
                setPageLineCount(paraSpace);
            }
            //mPageLineCount = (mVisibleHeight - paraSpace) / (mFontSize + mLineSpace);
        }
        return lines;
    }

    /***
     * 是否第一页
     * @return
     */
    public boolean isFirstPage(){
        return currentPage == 1 && mbBufferLen > 0 && curBeginPos == 0;
    }

    /***
     * 是否最后一页
     * @return
     */
    public boolean isLastPage(){
        return mbBufferLen > 0 && curEndPos >= mbBufferLen;
    }

    /***
     * 异步跳转到上一章末尾
     */
    public void pageToLast(){
        if(!mIsToPageLast) return;
        int ret = openBook(currentChapter, new int[]{0, 0});
        if(ret > 0){
            mLines = pageLast();
            onPageChanged(currentChapter, currentPage);
            mIsToPageLast = false;
        }
    }

    /**
     * 获取最后一页的内容。比较繁琐，待优化
     *
     * @return
     */
    public Vector<String> pageLast() {
        String strParagraph = "";
        Vector<String> lines = new Vector<>();
        currentPage = 0;
        //load first page to last page
        while (curEndPos < mbBufferLen) {
            int paraSpace = 0;
            setPageLineCount(0);
            curBeginPos = curEndPos;
            while ((lines.size() < mPageLineCount) && (curEndPos < mbBufferLen)) {
                byte[] parabuffer = readParagraphForward(curEndPos);
                curEndPos += parabuffer.length;
                try {
                    strParagraph = new String(parabuffer, charset);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                strParagraph = strParagraph.replaceAll("\r\n", "  ");
                strParagraph = strParagraph.replaceAll("\n", " "); // 段落中的换行符去掉，绘制的时候再换行

                while (strParagraph.length() > 0) {
                    int paintSize = mPaint.breakText(strParagraph, true, mVisibleWidth, null);
                    lines.add(strParagraph.substring(0, paintSize));
                    strParagraph = strParagraph.substring(paintSize);
                    if (lines.size() >= mPageLineCount) {
                        break;
                    }
                }
                lines.set(lines.size() - 1, lines.get(lines.size() - 1) + "@");

                if (strParagraph.length() != 0) {
                    try {
                        curEndPos -= (strParagraph).getBytes(charset).length;
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
                if(lines.size() < mPageLineCount){
                    paraSpace += mLineSpace;
                    setPageLineCount(paraSpace);
                }
               // mPageLineCount = (mVisibleHeight - paraSpace) / (mFontSize + mLineSpace);
            }
            if (curEndPos < mbBufferLen) {
                lines.clear();
            }
            currentPage++;
        }
        //SettingManager.getInstance().saveReadProgress(bookId, currentChapter, curBeginPos, curEndPos);
        return lines;
    }

    /**
     * 读取下一段落
     *
     * @param curEndPos 当前页结束位置指针
     * @return
     */
    private byte[] readParagraphForward(int curEndPos) {
        byte b0;
        int i = curEndPos;
        while (i < mbBufferLen) {
            b0 = mbBuff.get(i++);
            if (b0 == 0x0a) {
                break;
            }
        }
        int nParaSize = i - curEndPos;
        byte[] buf = new byte[nParaSize];
        for (i = 0; i < nParaSize; i++) {
            buf[i] = mbBuff.get(curEndPos + i);
        }
        return buf;
    }

    /**
     * 读取上一段落
     *
     * @param curBeginPos 当前页起始位置指针
     * @return
     */
    private byte[] readParagraphBack(int curBeginPos) {
        byte b0;
        int i = curBeginPos - 1;
        while (i > 0) {
            b0 = mbBuff.get(i);
            if (b0 == 0x0a && i != curBeginPos - 1) {
                i++;
                break;
            }
            i--;
        }
        int nParaSize = curBeginPos - i;
        byte[] buf = new byte[nParaSize];
        for (int j = 0; j < nParaSize; j++) {
            buf[j] = mbBuff.get(i + j);
        }
        return buf;
    }

    public boolean hasNextPage() {
        return currentChapter < chaptersList.size() || curEndPos < mbBufferLen;
    }

    public boolean hasPrePage() {
        return currentChapter > 1 || (currentChapter == 1 && curBeginPos > 0);
    }

    /**
     * 跳转下一页
     */
    public BookStatus nextPage(boolean isFromUser) {
        if (!hasNextPage()) { // 最后一章的结束页
            return BookStatus.NO_NEXT_PAGE;
        } else {
            tempChapter = currentChapter;
            tempBeginPos = curBeginPos;
            tempEndPos = curEndPos;
            if (curEndPos >= mbBufferLen) { // 中间章节结束页
                currentChapter++;
                int ret = openBook(currentChapter, new int[]{0, 0}); // 打开下一章
                //打开失败
                if (ret == 0) {
                    //避免1,2章一起乱跳
                    if(curEndPos > 0)
                        onLoadChapterFailure(currentChapter,isFromUser,0,0);
                    //加载失败时应该继续设置到下一章，以便翻页返回
                   /* currentChapter--;
                    curBeginPos = tempBeginPos;
                    curEndPos = tempEndPos;*/
                    currentPage = 0;
                    curBeginPos = 0;
                    curEndPos = 0;
                    mLines.clear();
                    //TODO
                    //onChapterChanged(currentChapter);
                    //onPageChanged(currentChapter, currentPage);
                    return BookStatus.NEXT_CHAPTER_LOAD_FAILURE;
                } else {
                    currentPage = 0;
                    //onChapterChanged(currentChapter);
                }
            } else {
                curBeginPos = curEndPos; // 起始指针移到结束位置
            }
            mLines.clear();
            mLines = pageDown(); // 读取一页内容
            currentPage++;
            onPageChanged(currentChapter, currentPage);
        }
        return BookStatus.LOAD_SUCCESS;
    }

    //
    private boolean mIsToPageLast=false;
    /**
     * 跳转上一页
     */
    public BookStatus prePage(boolean isFromUser) {
        if (!hasPrePage()) { // 第一章第一页
            return BookStatus.NO_PRE_PAGE;
        } else {
            // 保存当前页的值
            tempChapter = currentChapter;
            tempBeginPos = curBeginPos;
            tempEndPos = curEndPos;
            if (curBeginPos <= 0) {
                currentChapter--;
                int ret = openBook(currentChapter, new int[]{0, 0});

                if (ret == 0) {
                    onLoadChapterFailure(currentChapter,isFromUser,0,0);
                    //currentChapter++;
                    mIsToPageLast=true;
                    mLines.clear();
                    //TODO
                    //onChapterChanged(currentChapter);
                    //onPageChanged(currentChapter, 1);
                    return BookStatus.PRE_CHAPTER_LOAD_FAILURE;
                } else { // 跳转到上一章的最后一页
                    mLines.clear();
                    mLines = pageLast();
                    //onChapterChanged(currentChapter);
                    onPageChanged(currentChapter, currentPage);
                    return BookStatus.LOAD_SUCCESS;
                }
            }
            mLines.clear();
            pageUp(); // 起始指针移到上一页开始处
            mLines = pageDown(); // 读取一页内容
            currentPage--;
            onPageChanged(currentChapter, currentPage);
        }
        return BookStatus.LOAD_SUCCESS;
    }

    public void cancelPage(BaseReadView.FlipDirection flipDirection, boolean isFromUser) {
        currentChapter = tempChapter;
        curBeginPos = tempBeginPos;
        curEndPos = curBeginPos;
        if(flipDirection == BaseReadView.FlipDirection.RIGHT){
            currentPage--;
        }else{
            currentPage++;
        }

        int ret = openBook(currentChapter, new int[]{curBeginPos, curEndPos});
        if (ret == 0) {
            onLoadChapterFailure(currentChapter,false,0,0);
            return;
        }
        mLines.clear();
        mLines = pageDown();
    }

    /**
     * 获取当前阅读位置
     *
     * @return index 0：起始位置 1：结束位置
     */
    public int[] getPosition() {
        return new int[]{currentChapter, curBeginPos, curEndPos};
    }

    public String getHeadLineStr() {
        if (mLines != null && mLines.size() > 1) {
            return mLines.get(0);
        }
        return "";
    }

    /**
     * 设置字体大小
     *
     * @param sp 单位：sp
     */
    public void setTextFont(int sp) {
        //LogUtils.i("fontSize=" + sp);
        mFontSize = (int)ScreenUtil.sp2px(sp);
        setFontHeight();
        setLineSpace();
        mPaint.setTextSize(mFontSize);
        setPageLineCount(0);
        //set same pointer,then invoke nextpage() to refresh
        curEndPos = curBeginPos;
        mLines.clear();
        mLines = pageDown();
        //nextPage(false);
    }

    private void setLineSpace(){
        mLineSpace = mFontHeight/4*mLineSpaceRatio;
    }

    public void setLineSpaceRatio(int ratio){
        mLineSpaceRatio=ratio;
        setFontHeight();
        setLineSpace();
        curEndPos = curBeginPos;
        //nextPage(false);
        mLines.clear();
        mLines = pageDown();
    }


    /**
     * 设置字体颜色
     *
     * @param textColor
     * @param titleColor
     */
    public void setTextColor(int textColor, int titleColor) {
        mPaint.setColor(textColor);
        mTitlePaint.setColor(titleColor);
    }

    public int getTextFont() {
        return mFontSize;
    }

    /**
     * 根据百分比，跳到目标位置
     *
     * @param persent
     */
    public void setPercent(int persent) {
        float a = (float) (mbBufferLen * persent) / 100;
        curEndPos = (int) a;
        if (curEndPos == 0) {
            nextPage(false);
        } else {
            nextPage(false);
            prePage(false);
            nextPage(false);
        }
    }

    public void setBgBitmap(Bitmap BG) {
        mBookPageBg = BG;
    }

    public void setOnReadStateChangeListener(BaseReadView.IOnReadStateChangeListener listener) {
        this.listener = listener;
    }

    private void onChapterChanged(int chapter) {
        if (listener != null)
            listener.onChapterChanged(chapter);
    }

    private void onPageChanged(int chapter, int page) {
        if (listener != null)
            listener.onPageChanged(chapter, page);
    }

    public void onLoadChapterFailure(int chapter,boolean isFromUser,int beginPos,int endPos) {
        if (listener != null)
            listener.onLoadChapterFailure(chapter,isFromUser,beginPos,endPos);
    }

    public void convertBetteryBitmap() {
        batteryView = (ProgressBar) LayoutInflater.from(mContext).inflate(R.layout.layout_battery_progress, null);
        batteryView.setProgressDrawable(ContextCompat.getDrawable(mContext,
                        R.drawable.seekbar_battery_bg));
        batteryView.setProgress(battery);
        //batteryView.setRotationX(90);
        batteryView.setDrawingCacheEnabled(true);
        batteryView.measure(View.MeasureSpec.makeMeasureSpec(BATTERY_WIDTH, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(BATTERY_HEIGHT, View.MeasureSpec.EXACTLY));
        batteryView.layout(0, 0, batteryView.getMeasuredWidth(), batteryView.getMeasuredHeight());
        batteryView.buildDrawingCache();
        //batteryBitmap = batteryView.getDrawingCache();
        // tips: @link{https://github.com/JustWayward/BookReader/issues/109}
        batteryBitmap = Bitmap.createBitmap(batteryView.getDrawingCache());
        batteryView.setDrawingCacheEnabled(false);
        batteryView.destroyDrawingCache();

    }

    public void setBattery(int battery) {
        this.battery = battery;
        convertBetteryBitmap();
    }

    public void setTime(String time) {
        this.time = time;
    }

    public void recycle() {
        if (mBookPageBg != null && !mBookPageBg.isRecycled()) {
            mBookPageBg.recycle();
            mBookPageBg = null;
            LogUtils.d("mBookPageBg recycle");
        }

        if (batteryBitmap != null && !batteryBitmap.isRecycled()) {
            batteryBitmap.recycle();
            batteryBitmap = null;
            LogUtils.d("batteryBitmap recycle");
        }
    }
}
